package com.lyncs.ods.modules.company.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyncs.ods.common.web.RequestHolder;
import com.lyncs.ods.constant.LyncsOdsConstant;
import com.lyncs.ods.modules.company.mapper.CompanyInfoMapper;
import com.lyncs.ods.modules.company.model.CompanyContactInfo;
import com.lyncs.ods.modules.company.model.CompanyInfo;
import com.lyncs.ods.modules.company.model.ContactInfo;
import com.lyncs.ods.modules.company.service.CompanyContactInfoService;
import com.lyncs.ods.modules.company.service.CompanyInfoService;
import com.lyncs.ods.modules.txn.model.TxnCommonInfo;
import com.lyncs.ods.modules.user.service.CompanyUserRelationService;
import com.lyncs.ods.resp.CompanyShortInfoResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 公司账号信息表 服务实现类
 * </p>
 *
 * @author alex
 * @since 2022-03-29
 */
@Service
@Slf4j
public class CompanyInfoServiceImpl extends ServiceImpl<CompanyInfoMapper, CompanyInfo> implements CompanyInfoService {

    @Autowired
    private CompanyUserRelationService companyUserRelationService;
    @Autowired
    private CompanyContactInfoService companyContactInfoService;

    @Override
    public String getLoginCompanyName() {
        Long companyId = RequestHolder.getCompanyId();
        CompanyInfo companyInfo = getCompanyInfo(companyId, null);
        if (companyInfo == null) {
            log.error("getLoginCompanyName err, companyId:{}", companyId);
            return null;
        }
        return companyInfo.getShortName();
    }

    @Override
    public CompanyInfo getCompanyInfo(Long companyId, Integer status) {
        return this.lambdaQuery().eq(CompanyInfo::getId, companyId).eq(Objects.nonNull(status), CompanyInfo::getStatus, status).one();
    }

    @Override
    public List<CompanyInfo> getAvailableCompanyInfos(List<Long> companyIds) {
        return this.lambdaQuery().in(CompanyInfo::getId, companyIds).ne(CompanyInfo::getStatus, LyncsOdsConstant.CompanyStatus.DISABLE.getKey()).list();
    }

    @Override
    public CompanyInfo getAvailableCompanyInfo(Long companyId) {
        return this.lambdaQuery().eq(CompanyInfo::getId, companyId).ne(CompanyInfo::getStatus, LyncsOdsConstant.CompanyStatus.DISABLE.getKey()).one();
    }

    @Override
    public <T extends TxnCommonInfo> Map<Long, CompanyInfo> getTxnCompanyInfos(@NotNull List<T> list) {
        List<Long> companyIds = list.stream().flatMap(t -> Stream.of(t.getBuyerId(), t.getSellerId())).distinct().collect(Collectors.toList());
        return getCompanyInfos(companyIds, null, " ORDER BY id").stream().collect(Collectors.toMap(CompanyInfo::getId, o -> o));
    }

    @Override
    public List<CompanyInfo> getCompanyInfos(@NotNull List<Long> companyIds, Integer status, @NotNull String sortSql) {
        return this.lambdaQuery().in(CompanyInfo::getId, companyIds).eq(Objects.nonNull(status), CompanyInfo::getStatus, status).last(sortSql).list();
    }

    @Override
    public CompanyInfo getValidCompanyInfo(Long companyId) {
        return getCompanyInfo(companyId, LyncsOdsConstant.EnableStatus.ENABLE.getKey());
    }

    private <T extends TxnCommonInfo> List<String> getNotifyTos(List<T> list, Function<ContactInfo, String> columnFunc, Function<Long, List<String>> userNotifyFunc) {
        List<String> tos = getCompanyTos(list, columnFunc);
        //B类企业只查自身的手机/邮箱，不查员工的
        for (T t : list) {
            if (!t.getCreatorCompanyId().equals(t.getBuyerId())) {
                tos.addAll(userNotifyFunc.apply(t.getBuyerId()));
            }
            if (!t.getCreatorCompanyId().equals(t.getSellerId())) {
                tos.addAll(userNotifyFunc.apply(t.getSellerId()));
            }
        }
        return tos.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
    }

    @Override
    public <T extends TxnCommonInfo> List<String> getNotifyEmail(T t) {
        return getNotifyTos(List.of(t), ContactInfo::getEmail, (companyId) -> companyUserRelationService.getCompanyUserEmail(companyId));
    }

    @Override
    public <T extends TxnCommonInfo> List<String> getNotifyPhone(T t) {
        return getNotifyTos(List.of(t), ContactInfo::getTelephone, (companyId) -> companyUserRelationService.getCompanyUserPhone(companyId));
    }

    @Override
    public <T extends TxnCommonInfo> List<String> getNotifyEmail(List<T> list) {
        return getNotifyTos(list, ContactInfo::getEmail, (companyIds) -> companyUserRelationService.getCompanyUserEmail(companyIds));
    }

    @Override
    public <T extends TxnCommonInfo> List<String> getNotifyPhone(List<T> list) {
        return getNotifyTos(list, ContactInfo::getTelephone, (companyIds) -> companyUserRelationService.getCompanyUserPhone(companyIds));
    }

    /**
     * 获取收件人手机号/邮箱
     */
    private <T extends TxnCommonInfo> List<String> getCompanyTos(List<T> list, Function<ContactInfo, String> columnFunc) {
        List<String> tos = new ArrayList<>();
        Map<String, CompanyContactInfo> txnConcatCompanyMap = companyContactInfoService.getTxnConcatNameMap(list);
        txnConcatCompanyMap.values().forEach(i -> {
            ContactInfo contactInfo = i.getContactDetail();
            String to = columnFunc.apply(contactInfo);
            if (StringUtils.isNotEmpty(to)) {
                tos.add(to);
            }
        });
        return tos;
    }

    @Override
    public <T extends TxnCommonInfo> Map<Long, CompanyShortInfoResp> getTxnCompanyRespInfos(List<T> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Map.of();
        }
        Long companyId = RequestHolder.getCompanyIdAllowNull();
        List<Long> companyIds = new ArrayList<>();
        List<CompanyInfo> companyInfos;
        if (companyId == null) {
            //没带登录态时直接查企业简称
            companyIds = list.stream().flatMap(i -> Stream.of(i.getBuyerId(), i.getSellerId())).distinct().collect(Collectors.toList());
            companyInfos = this.lambdaQuery().in(CompanyInfo::getId, companyIds).list();
            return companyInfos.stream().collect(Collectors.toMap(CompanyInfo::getId, info -> new CompanyShortInfoResp()
                    .setAvatarUrl(info.getAvatarUrl())
                    .setCompanyId(info.getId())
                    .setShortName(info.getShortName())
                    .setName(info.getName())
                    .setRegister(LyncsOdsConstant.CompanyStatus.ENABLE.getKey().equals(info.getStatus()))
                    .setAddress(null)));
        }
        //当前企业
        for (T t : list) {
            if (!t.getSellerId().equals(companyId)) {
                companyIds.add(t.getSellerId());
            }
            if (!t.getBuyerId().equals(companyId)) {
                companyIds.add(t.getBuyerId());
            }
        }
        Map<Long, CompanyShortInfoResp> companyShortInfoRespMap = new HashMap<>();
        companyIds = companyIds.stream().distinct().collect(Collectors.toList());
        List<CompanyContactInfo> contactInfos = companyContactInfoService.lambdaQuery().eq(CompanyContactInfo::getCompanyId, companyId)
                .in(CompanyContactInfo::getRelationId, companyIds)
                .eq(CompanyContactInfo::getStatus, LyncsOdsConstant.BindStatus.BIND.getKey())
                .list();
        //当前企业
        companyIds.add(companyId);
        companyInfos = this.lambdaQuery().in(CompanyInfo::getId, companyIds).list();
        Map<Long, CompanyInfo> companyInfoMap = companyInfos.stream().collect(Collectors.toMap(CompanyInfo::getId, o -> o));
        for (CompanyContactInfo contactInfo : contactInfos) {
            CompanyInfo companyInfo = companyInfoMap.get(contactInfo.getRelationId());
            if (Objects.isNull(companyInfo) || companyShortInfoRespMap.containsKey(contactInfo.getRelationId())) {
                continue;
            }
            CompanyShortInfoResp companyShortInfoResp = new CompanyShortInfoResp()
                    .setAvatarUrl(companyInfo.getAvatarUrl())
                    .setCompanyId(companyInfo.getId())
                    .setShortName(contactInfo.getNickname())
                    .setName(companyInfo.getName())
                    .setRegister(contactInfo.getInitCompanyId() == null || !contactInfo.getRelationId().equals(contactInfo.getInitCompanyId()))
                    .setAddress(null)
                    .setRelated(Boolean.TRUE);
            companyShortInfoRespMap.put(contactInfo.getRelationId(), companyShortInfoResp);
        }
        //未在通讯录好友中的企业
        if (CollectionUtils.isNotEmpty(companyInfos)) {
            for (CompanyInfo companyInfo : companyInfos) {
                if (companyShortInfoRespMap.containsKey(companyInfo.getId())) {
                    continue;
                }
                CompanyShortInfoResp companyShortInfoResp = new CompanyShortInfoResp()
                        .setAvatarUrl(companyInfo.getAvatarUrl())
                        .setCompanyId(companyInfo.getId())
                        .setShortName(companyInfo.getShortName())
                        .setName(companyInfo.getName())
                        .setRegister(LyncsOdsConstant.CompanyStatus.ENABLE.getKey().equals(companyInfo.getStatus()))
                        .setAddress(null);
                companyShortInfoRespMap.put(companyInfo.getId(), companyShortInfoResp);
            }
        }
        return companyShortInfoRespMap;
    }
}
